<template>
  <div class="age-grid">
    <el-form label-position="top" label-width="auto">
      <el-form-item label="公历生日">
        <el-date-picker
          v-model="state.birth"
          type="date"
          placeholder="请选择公历生日"
          format="YYYY年MM月DD日"
          value-format="YYYY-MM-DD" />
      </el-form-item>

      <div class="card">
        <div class="section-title center">计算结果</div>
        <div class="result-grid">
          <div class="age-block">
            <div class="muted">年龄</div>
            <div class="age-row">
              <div class="age-value">
                {{ ageYears }}<span class="suffix">年</span>
              </div>
              <div class="sub-value">{{ ageMonths }}个月{{ ageDays }}天</div>
            </div>
          </div>
          <div class="inline-badges">
            <el-tag size="small" type="info" effect="plain"
              >生肖：{{ zodiac }}</el-tag
            >
            <el-tag size="small" type="info" effect="plain"
              >星座：{{ constellation }}</el-tag
            >
          </div>
        </div>
      </div>

      <div class="card">
        <div class="section-title center">下一个生日</div>
        <div class="center-wrap">
          <div class="age-value">还有{{ daysToNextBirthday }}天</div>
          <div class="sub-value">公历：{{ nextBirthdayText }}</div>
        </div>
      </div>

      <div class="card">
        <div class="section-title center">您在地球生活了</div>
        <div class="lived-grid">
          <div>
            <div class="muted">年</div>
            <div class="num">{{ lived.y }}</div>
          </div>
          <div>
            <div class="muted">月</div>
            <div class="num">{{ lived.m }}</div>
          </div>
          <div>
            <div class="muted">日</div>
            <div class="num">{{ lived.d }}</div>
          </div>
          <div>
            <div class="muted">小时</div>
            <div class="num">{{ lived.h }}</div>
          </div>
        </div>
      </div>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ElDatePicker, ElForm, ElFormItem, ElTag } from "element-plus"
import { computed, onMounted, onUnmounted, reactive, ref, watch } from "vue"

type AgeState = {
  birth: string
}

const todayISO = new Date().toISOString().slice(0, 10)
const state = reactive<AgeState>({ birth: todayISO })

// helpers
function parseISO(v: string): Date {
  const [y, m, d] = v.split("-").map((x) => Number(x))
  return new Date(y, m - 1, d)
}
function daysInMonth(y: number, m: number): number {
  return new Date(y, m + 1, 0).getDate()
}

function pad2(n: number): string {
  return n < 10 ? `0${n}` : String(n)
}

// Age Y-M-D
const ageYears = computed(() => diffYMD().y)
const ageMonths = computed(() => diffYMD().m)
const ageDays = computed(() => diffYMD().d)

function diffYMD() {
  const b = parseISO(state.birth)
  const n = new Date()
  let y = n.getFullYear() - b.getFullYear()
  let m = n.getMonth() - b.getMonth()
  let d = n.getDate() - b.getDate()
  if (d < 0) {
    m -= 1
    const prevMonth = (n.getMonth() - 1 + 12) % 12
    const prevYear = prevMonth === 11 ? n.getFullYear() - 1 : n.getFullYear()
    d += daysInMonth(prevYear, prevMonth)
  }
  if (m < 0) {
    y -= 1
    m += 12
  }
  if (y < 0) return { y: 0, m: 0, d: 0 }
  return { y, m, d }
}

// Next birthday
const nextBirthday = computed(() => {
  const b = parseISO(state.birth)
  const now = new Date()
  let y = now.getFullYear()
  let nb = new Date(y, b.getMonth(), b.getDate())
  // if today past this year's birthday, go next year
  if (
    nb.getTime() <
    new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime()
  ) {
    y += 1
    nb = new Date(y, b.getMonth(), b.getDate())
  }
  return nb
})

const daysToNextBirthday = computed(() => {
  const now = new Date()
  const start = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const target = nextBirthday.value
  const diff = Math.round(
    (target.getTime() - start.getTime()) / (24 * 3600 * 1000)
  )
  return diff
})

const nextBirthdayText = computed(() => {
  const d = nextBirthday.value
  return `${d.getFullYear()}年${pad2(d.getMonth() + 1)}月${pad2(d.getDate())}日`
})

// Zodiac (生肖)
const animals = [
  "鼠",
  "牛",
  "虎",
  "兔",
  "龙",
  "蛇",
  "马",
  "羊",
  "猴",
  "鸡",
  "狗",
  "猪"
]
const zodiac = computed(() => {
  const y = parseISO(state.birth).getFullYear()
  const idx = (y - 1900) % 12
  return animals[(idx + 12) % 12]
})

// Constellation
function getConstellation(month: number, day: number): string {
  // 使用常见中文星座分界（含起始日，下一星座起始日前一天）
  const z = [
    [1, 20, "水瓶座"],
    [2, 19, "双鱼座"],
    [3, 21, "白羊座"],
    [4, 20, "金牛座"],
    [5, 21, "双子座"],
    [6, 22, "巨蟹座"],
    [7, 23, "狮子座"],
    [8, 23, "处女座"],
    [9, 23, "天秤座"],
    [10, 24, "天蝎座"],
    [11, 23, "射手座"],
    [12, 22, "摩羯座"],
    [12, 32, "水瓶座"]
  ] as Array<[number, number, string]>
  for (let i = 0; i < z.length - 1; i++) {
    const [m1, d1, name] = z[i]
    const [m2, d2] = z[i + 1]
    if ((month === m1 && day >= d1) || (month === m2 && day < d2)) return name
  }
  return "摩羯座"
}
const constellation = computed(() => {
  const b = parseISO(state.birth)
  return getConstellation(b.getMonth() + 1, b.getDate())
})

// lived time ticker
const lived = reactive({ y: 0, m: 0, d: 0, h: 0 })
let timer: any
function updateLived() {
  const b = parseISO(state.birth)
  const now = new Date()
  const ymd = diffYMD()
  // 年：整年数；月：累计总月数；日：累计总天数；小时：累计总小时数
  lived.y = ymd.y
  lived.m = ymd.y * 12 + ymd.m
  const ms = now.getTime() - b.getTime()
  const totalDays = Math.floor(ms / 86400000)
  const totalHours = Math.floor(ms / 3600000)
  lived.d = Math.max(0, totalDays)
  lived.h = Math.max(0, totalHours)
}

onMounted(() => {
  updateLived()
  timer = setInterval(updateLived, 1000)
})
onUnmounted(() => clearInterval(timer))

watch(
  () => state.birth,
  () => updateLived()
)
</script>

<style scoped>
.age-grid {
  display: grid;
  gap: 10px;
}

.card {
  margin-bottom: 10px;
  padding: 12px;
  border-radius: 10px;
  border: 1px solid var(--el-border-color-lighter, #ebeef5);
  background: var(--card-bg, rgba(60, 60, 67, 0.03));
  line-height: 1.6;
}

.section-title {
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 6px;
}

.section-title.center {
  text-align: center;
}

.muted {
  color: var(--muted);
}

.result-grid {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  justify-items: center;
  text-align: center;
  gap: 4px;
}

.age-row {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 12px;
}

.center-wrap {
  display: grid;
  place-items: center;
  gap: 4px;
}

.inline-badges {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 6px;
}

.age-value {
  font-size: 24px;
  font-weight: 700;
}

.suffix {
  font-size: 12px;
  margin-left: 4px;
}

.sub-value {
  color: var(--text-2, #606266);
}

.lived-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  text-align: center;
  gap: 10px;
}

.num {
  font-size: 20px;
  font-weight: 700;
}
</style>
